
from copy import deepcopy
from pyglet.gl import *
from Vector import Vector3, Vector2, Quaternion

class Camera:
    def __init__(self, pos, tar):
        self.pos = pos
        self.tar = tar
        self.fow = tar - pos
        self.up = Vector3(0, 1, 0)
        self.str = self.fow.cross(self.up)
        self._fix_up_and_strafe()

    def _fix_up_and_strafe(self):
        self.fow.normalize()
        self.str = self.fow.cross(self.up)
        self.str.y = 0
        self.str.normalize()
        self.up = self.str.cross(self.fow)
        self.up.normalize()

    def turn(self, hangle, vangle):
        self.fow = Quaternion.new_rotate_axis(hangle, self.up) * self.fow
        self.fow = Quaternion.new_rotate_axis(vangle, self.str) * self.fow
        self._fix_up_and_strafe()

    def orbit(self, hangle, vangle, focal_distance):
        focus = self.pos + (self.fow & focal_distance)
        back = -(self.fow & focal_distance)
        back = Quaternion.new_rotate_axis(hangle, self.up) * back
        back = Quaternion.new_rotate_axis(vangle, self.str) * back
        self.pos = focus + back
        self.fow = -back
        self._fix_up_and_strafe()

    def zoom(self, amount):
        self.pos += self.fow & amount

    def move(self, fb, ss):
        if fb:
            self.pos += self.fow.normalized() * fb
        if ss:
            self.pos += self.str.normalized() * ss

    def move_level(self, fb, ss):
        if fb:
            nfow = deepcopy(self.fow)
            nfow.y = 0
            nfow &= 1.0
            self.pos += nfow * fb
        if ss:
            self.pos += self.str.normalized() * -ss

    def ensure_above(self, alt):
        self.pos.y = max(alt, self.pos.y)

    def use(self):
        pv = self.pos + self.fow
        gluLookAt(self.pos.x, self.pos.y, self.pos.z \
                 ,pv.x, pv.y, pv.z \
                 ,self.up.x, self.up.y, self.up.z)
